class Project extends Activity{

    Date startDate
    Date endDate
    
    static hasMany = [budgets : Budget]

    static constraints = {
        amountOfHour(nullable:true)
        startDate(nullable:false,validator: {
            val, obj ->
            val < obj.properties['endDate']
            }
        )
        budgets(nullable:true)
        endDate(nullable:false,validator: {
            val, obj ->
            val > obj.properties['startDate']
            }
        )
    }


    public Boolean budgetExists(int year)
    {
        if(DBConnection.isConnectionStarted() && this.budgets == null){
           def budg = DBConnection.getBudgetList(this)
           for(Budget b in budg){
                if(b?.year == year){
                    return true
                }
            }
        }
        else{
            for(Budget b in budgets){
                if(b?.year == year){
                    return true
                }
            }
        }

        return false
    }

    public Budget currentBudget(){
        Date d = new Date();
        return this.budget(d.getYear());
    }

    /* Get the budget of the year given in parameters
     * If it doesn't exist, let's create it and return it
     * */
    public Budget budget(int year){

        if(DBConnection.isConnectionStarted() && this.budgets==null){
           def budg = DBConnection.getBudgetList(this)
           for(Budget b in budg){
                if(b?.year == year){
                    b.project = this
                    return b;
                }
            }
//            println("create budget")
            Budget b = new Budget(year:year, project:this);
            DBConnection.saveBudget(this,b);
//            def budg2 = DBConnection.getBudgetList(this)
//            for(Budget b2 in budg2){
//                if(b2?.year == year){
////                    println("budg2 returned:"+b)
//                    b2.project = this
//                    return b2;
//                }
//            }
            return b
        }
        else{
            for(Budget b in budgets){
                if(b?.year == year){
//                    println("budg3 returned:"+b)
                    b.project = this
                    return b;
                }
            }
            Budget b = new Budget(year:year, project:this);
            this.addToBudgets(b);
//            println("new budget returned:"+b)
            return b;
        }
    }

    

    /* Add employee to project */
     public void addEmployee(Employee e){
        Date d = new Date();
        if(e != null){
            Whoa w = new Whoa(member:e, year:d.getYear(), hours:0, worksInProject:this);

            if(DBConnection.isConnectionStarted()){
                DBConnection.saveWhoa(w,this)
            }
            else{
                this.addToAmountOfHour(w);
            }

        }
        else{
            System.out.println("Något gick fel:" + e)
        }
    }

    //TODO Should this really exist?
    public Float calcTotalCost(int fromYear, int toYear){
        return calcKnownCost(fromYear,toYear)+calcExpectedCost(fromYear,toYear)
    }

    public Float calcTotalIncome(int fromYear, int toYear){
        return calcKnownIncome(fromYear,toYear)+calcExpectedIncome(fromYear,toYear)
    }

    public float calcKnownCost(int fromYear, int toYear){
        Float sum = 0.0f
        for(Budget budget: budgets)
        {
            if(budget.year >= fromYear && budget.year <= toYear)
            {
                print("X")
                sum += budget.knownVariableCost
                sum += budget.calcTotalFixedCost()
            }
        }
//        println(project?.name+ ":calcKnownCost: "+ sum.toString() + ", "+ fromYear.toString() + ", "+toYear.toString())
        return sum
    }

    public Float calcExpectedCost(int fromYear, int toYear){
        Float sum = 0.0f
        for(Budget budget: budgets)
        {
            if(budget.year >= fromYear && budget.year <= toYear)
            {
                print("X")
                sum += budget.calcExpectedVariableCost()
            }
        }
//        println(project?.name+ ":calcExpectedCost: "+ sum.toString() + ", "+ fromYear.toString() + ", "+toYear.toString())
        return sum
    }

    
    public Float calcKnownIncome(int fromYear, int toYear){
        Float sum = 0
        for(Budget budget: budgets)
        {
            if(budget.year >= fromYear && budget.year <= toYear)
            {
                print("X")
                sum += budget.knownTotalIncome
            }
        }
//        println(project?.name+ ":calcKnownIncome: "+ sum.toString() + ", "+ fromYear.toString() + ", "+toYear.toString())
        return sum
    }

    public Float calcExpectedIncome(int fromYear, int toYear){
        Float sum = 0
        for(Budget budget: budgets)
        {
            if(budget.year >= fromYear && budget.year <= toYear)
            {
                print("X")
                sum += budget.expectedTotalIncome
            }
        }
//        println(project?.name+ ":calcExpectedIncome: "+ sum.toString() + ", "+ fromYear.toString() + ", "+toYear.toString())
        return sum
    }

    public Float calcCurrentBalance(){
        return this.currentBudget().calcBalance()
    }

    public Float calcIncomingBalance(){
        return calcTotalIncome(0, (new Date()).getYear()-1) - calcTotalCost(0, (new Date()).getYear()-1)
    }

    //Returns the status of the project based on date
    public String calcStatus()
    {
        Date now = new Date()
        if(this.startDate>now){
           return "Planned"
        }
            

        if(this.endDate < now){
            return "Done"
        }

        if(this.startDate <= now && this.endDate >= now){
            return "Progressing"
        }

      return "Erroneous"
    }

    static Float sumCalculationResultBudget(session) {
        float sum = 0
        def access = session.access
        access.refresh()

        def list = access.getList("project")

        for (Project a in list) {

            if (ModeAccess.isAvailableInCurrentMode(session.mode,a.mode)) {
                   
                    sum += a?.currentBudget()?.calculationResult()
            }
        }
        return sum
    }

    static Float calcTotalIncomingBalance(session){
        float sum = 0
        def access = session.access
        access.refresh()

        def list = access.getList("project")

        for (Project a in list) {

            if (ModeAccess.isAvailableInCurrentMode(session.mode,a.mode)) {
                    
                    sum += a?.currentBudget()?.incomingBalance
            }
        }
        return sum
    }

    static Float calcTotalOutgoingBalance(session){
        float sum = 0
        def access = session.access
        access.refresh()

        def list = access.getList("project")

        for (Project a in list) {

            if (ModeAccess.isAvailableInCurrentMode(session.mode,a.mode)) {
                    
                    sum += a?.currentBudget()?.calcOutgoingBalance();
            }
        }
        return sum
    }

    

    String toString(){
        return "(" +  this.activityId + "), " + this.name;
    }




    
}
